package com.yale.elasticsearch.service.query;

import com.yale.elasticsearch.dto.BoolQueryDTO;
import com.yale.elasticsearch.model.entity.UserInfo;
import com.yale.elasticsearch.model.request.QuerySearch;
import com.yale.elasticsearch.utils.ElasticsearchQueryBuilder;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch._types.query_dsl.BoolQuery;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.HitsMetadata;
import co.elastic.clients.json.JsonData;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 布尔查询
 */
@Service
@Slf4j
public class BoolQueryService {

    @Resource
    private ElasticsearchClient elasticsearchClient;
//    @Resource
//    ElasticsearchQueryBuilder elasticsearchQueryBuilder;

    /**
     * 布尔查询
     */
    public Object boolQuery(BoolQueryDTO boolQueryDTO) {
        Object result = "";
        try {
            if (boolQueryDTO == null) {
                return "参数值为空";
            }
            SearchRequest searchRequest = null;
            if (boolQueryDTO.getQueryType() == null || boolQueryDTO.getQueryType().size() == 0) {
                // 创建查询请求对象
                searchRequest = SearchRequest.of(s -> s.index(boolQueryDTO.getIndexName()));
            } else {
                ElasticsearchQueryBuilder elasticsearchQueryBuilder = new ElasticsearchQueryBuilder();
                // 添加动态查询条件
                for (BoolQueryDTO.QueryTypeDTO queryType : boolQueryDTO.getQueryType()) {
                    if (queryType.getQuery() != null || queryType.getQuery().size() > 0) {
                        switch (queryType.getType()) {
                            case 1:
                                List<String> values = new ArrayList<>();
                                List<QuerySearch> querySearchList = new ArrayList<>();
                                String field = null;
                                for(BoolQueryDTO.QueryDTO query : queryType.getQuery()){
                                    //单字段多值
                                    if (query.getField() != null && query.getValueForStringArray() != null) {
                                        if (query.getValueForString() != null) {
                                            values = Arrays.asList(queryType.getQuery().get(0).getValueForString());
                                        }
                                        if (query.getValueForStringArray() != null) {
                                            values = Arrays.asList(query.getValueForStringArray());
                                        }
                                        field = query.getField();

                                    }else{
                                        //多字段多值
                                        QuerySearch querySearch = new QuerySearch();
                                        querySearch.setKey(query.getField());
                                        querySearch.setValue(query.getValueForString());
                                        querySearchList.add(querySearch);
                                    }
                                }
                                if(field != null && values.size() > 0){
                                    elasticsearchQueryBuilder.addMultiKeywordMatchQuery(field, values);
                                }
                                if(querySearchList.size() > 0){
                                    elasticsearchQueryBuilder.addMultiMatchQuery(querySearchList);
                                }
                                break;
                            case 2:
                                elasticsearchQueryBuilder.addBooleanFilter(queryType.getQuery().get(0).getField(), queryType.getQuery().get(0).getValueForBoolean());
                                break;
                            case 3:
                                Double min = null;
                                Double max = null;
                                if (queryType.getQuery().get(0).getValueForMinNumber() != null) {
                                    min = Double.parseDouble(queryType.getQuery().get(0).getValueForMinNumber());
                                }
                                if (queryType.getQuery().get(0).getValueForMaxNumber() != null) {
                                    max = Double.parseDouble(queryType.getQuery().get(0).getValueForMaxNumber());
                                }
                                elasticsearchQueryBuilder.addRangeFilterForNumber(queryType.getQuery().get(0).getField(), min, max);
                                break;
                            case 4:
                                elasticsearchQueryBuilder.addDateRangeFilterForDate(queryType.getQuery().get(0).getField(),
                                        queryType.getQuery().get(0).getValueForStartDate(), queryType.getQuery().get(0).getValueForEndDate());
                                break;
                        }
                        // 获取构建的 BoolQuery
                        BoolQuery boolQuery = elasticsearchQueryBuilder.build();
                        // 创建查询请求对象
                        searchRequest = SearchRequest.of(s -> s.index(boolQueryDTO.getIndexName()).query(q -> q.bool(boolQuery)));
                    }
                }
            }

            // 执行查询
            SearchResponse<JsonData> searchResponse = elasticsearchClient.search(searchRequest, JsonData.class);

            // 处理响应结果
            HitsMetadata<JsonData> hits = searchResponse.hits();
            List<Hit<JsonData>> hitList = hits.hits();
             List<UserInfo> userInfoList = new ArrayList<>();
            for (Hit<JsonData> hit : hitList) {
                // 将 JSON 转换成对象
                UserInfo userInfo = JSON.parseObject(hit.source().toJson().toString(), UserInfo.class);
                userInfoList.add(userInfo);
                // 输出查询信息
                log.info("打印查询信息：{}", JSON.toJSONString(userInfo));
            }

            result = userInfoList;

        } catch (IOException e) {
            log.error("Error executing search request: {}", e.getMessage());
        }
        return result;
    }

}
